package com.hzsoft.util;

import java.math.BigDecimal;
import org.apache.commons.lang.math.NumberUtils;
import org.apache.commons.lang.ArrayUtils;
import java.text.DecimalFormat;
import java.text.NumberFormat;

public class NumberUtil {

	private static final int DEF_DIV_SCALE = 10;

	public NumberUtil() {
	}

	/**
	 * 精度加法运算
	 * @param v1 被加数
	 * @param v2 加数
	 * @return 返回参数的和
	 */
	public static double add(double v1, double v2) {
		BigDecimal b1 = new BigDecimal(Double.toString(v1));
		BigDecimal b2 = new BigDecimal(Double.toString(v2));
		return b1.add(b2).doubleValue();
	}

	/**
	 * 精度减法运算
	 * @param v1  被减数
	 * @param v2  减数
	 * @return 返回参数的差
	 */
	public static double sub(double v1, double v2) {
		BigDecimal b1 = new BigDecimal(Double.toString(v1));
		BigDecimal b2 = new BigDecimal(Double.toString(v2));
		return b1.subtract(b2).doubleValue();
	}

	/**
	 * 精度乘法运算
	 * @param v1  被乘数
	 * @param v2  乘数
	 * @return 返回参数的积
	 */
	public static double mul(double v1, double v2) {
		BigDecimal b1 = new BigDecimal(Double.toString(v1));
		BigDecimal b2 = new BigDecimal(Double.toString(v2));
		return b1.multiply(b2).doubleValue();
	}

	/**
	 * 精度除法运算[10位小数]
	 * @param v1  被除数
	 * @param v2 除数
	 * @return 返回参数的商
	 */
	public static double div(double v1, double v2) {
		return div(v1, v2, DEF_DIV_SCALE);
	}

	/**
	 * 精度除发运算
	 * @param v1 被除数
	 * @param v2  除数
	 * @param scale 精确的小数位数
	 * @return 返回参数的商
	 */
	public static double div(double v1, double v2, int scale) {
		if (scale < 0) {
			throw new IllegalArgumentException("精度错误！");
		}
		if (v2 == 0) {
			return 0;
		}
		BigDecimal b1 = new BigDecimal(Double.toString(v1));
		BigDecimal b2 = new BigDecimal(Double.toString(v2));
		return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
	}

	/**
	 * 精度加法运算
	 * @param v1 被加数
	 * @param v2  加数
	 * @return 返回参数的和
	 */
	public static double add(String v1, String v2) {
		BigDecimal b1 = new BigDecimal(v1);
		BigDecimal b2 = new BigDecimal(v2);
		return b1.add(b2).doubleValue();
	}

	/**
	 * 精度减法运算
	 * @param v1 被减数
	 * @param v2  减数
	 * @return 返回参数的差
	 */
	public static double sub(String v1, String v2) {
		BigDecimal b1 = new BigDecimal(v1);
		BigDecimal b2 = new BigDecimal(v2);
		return b1.subtract(b2).doubleValue();
	}

	/**
	 * 精度乘法运算
	 * @param v1  被乘数
	 * @param v2 乘数
	 * @return 返回参数的积
	 */
	public static double mul(String v1, String v2) {
		BigDecimal b1 = new BigDecimal(v1);
		BigDecimal b2 = new BigDecimal(v2);
		return b1.multiply(b2).doubleValue();
	}

	/**
	 * 精度除法运算[10位小数]
	 * @param v1  被除数
	 * @param v2  除数
	 * @return 返回参数的商
	 */
	public static double div(String v1, String v2) {
		return div(v1, v2, DEF_DIV_SCALE);
	}

	/**
	 * 精度除发运算
	 * @param v1  被除数
	 * @param v2  除数
	 * @param scale 精确的小数位数
	 * @return 返回参数的商
	 */
	public static double div(String v1, String v2, int scale) {
		if (scale < 0) {
			throw new IllegalArgumentException("精度错误！");
		}
		if (v2.equals("0.0")) {
			return 0;
		}
		BigDecimal b1 = new BigDecimal(v1);
		BigDecimal b2 = new BigDecimal(v2);
		return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
	}

	/**
	 * 小数位四舍五入
	 * @param v  需要四舍五入的小数
	 * @param scale 小数点后保留几位
	 * @return 结果
	 */
	public static double round(double v, int scale) {
		if (scale < 0) {
			throw new IllegalArgumentException("精度错误！");
		}
		BigDecimal b = new BigDecimal(Double.toString(v));
		BigDecimal one = new BigDecimal("1");
		return b.divide(one, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
	}

	/**
	 * 小数位四舍五入
	 * @param v  需要四舍五入的小数
	 * @return 结果
	 */
	public static String round(double v) {
		return Double.toString(round(v, 2));
	}

	/**
	 * 去除科学计数法的显示方式
	 * @param s  转换的数字
	 * @return 转换后的字符串
	 */
	public static String round(String s) {
		double v = 0.0;
		try {
			v = Double.parseDouble(s);
		} catch (Exception ex) {
			return "0.0";
		}
		DecimalFormat format = new DecimalFormat("0.00");
		String value = format.format(v);
		return value;
	}

	public static String parseStr(String str) {
		String newString = "0.0";
		try {
			newString = new DecimalFormat().parse(str).toString();
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		return newString;
	}

	/**
	 * 格式化精度字符串，转换为货币格式。 默认保留小数点后两位(四舍五入)，三位为一个分组。
	 * @param parNum 被格式化的双精度数
	 * @return 返回格式化后的字符串
	 */
	public static String formatDecimal(double parNum) {
		String endString = null;
		DecimalFormat df = new DecimalFormat("###,##0.00");
		endString = df.format(parNum);
		return endString;
	}

	/**
	 * 格式化精度字符串，转换为货币格式 提供格式化参数 #表示位数，左端第一位或右端后一位如果是0将不显示。
	 * 0表示数字，左端第一位或右端最后一位如果是0将保留。 .表示小数点。 ,表示分组显示，限定在小数点左侧使用。
	 * @param parNum  被格式化的数字
	 * @param parFormat 格式化样式
	 * @return 返回格式化后的字符串
	 */
	public static String formatDecimal(double parNum, String parFormat) {
		if (parFormat == null || parFormat.equals("")) {
			return null;
		}
		String endString = null;
		DecimalFormat df = new DecimalFormat(parFormat);
		endString = df.format(parNum);
		return endString;
	}

	/**
	 * 格式化为科学计数法 默认格式为保留4个小数位
	 * @param parNum 被格式化的数字
	 * @return 返回格式化后的字符串
	 */
	public static String formatKXJS(double parNum) {
		String endString = null;
		DecimalFormat df = new DecimalFormat("0.0000E0");
		endString = df.format(parNum);
		return endString;
	}

	/**
	 * 格式化为科学计数法 提供格式化参数 #表示位数，左端第一位或右端后一位如果是0将不显示。 0表示数字，左端第一位或右端最后一位如果是0将保留。
	 * E表示科学计数法
	 * @param parNum 被格式化的数字
	 * @param parFormat  格式化样式
	 * @return 返回格式化后的字符串
	 */
	public static String formatKXJS(double parNum, String parFormat) {
		if (parFormat == null || parFormat.equals("")) {
			return null;
		}
		String endString = null;
		DecimalFormat df = new DecimalFormat(parFormat);
		endString = df.format(parNum);
		return endString;
	}

	/**
	 * 格式化为百分数 默认格式为保留小数点前后各2位。
	 * @param parNum  被格式化数
	 * @return 返回格式化后的字符串
	 */
	public static String formatBFB(double parNum) {
		String endString = null;
		DecimalFormat df = null;
		try {
			df = (DecimalFormat) NumberFormat.getPercentInstance();
			df.applyPattern("0.00%");
			endString = df.format(parNum);
		} catch (Exception ex) {

			ex.printStackTrace();
		}
		return endString;
	}

	/**
	 * 格式化为百分数 提供格式化参数 #表示位数，左端第一位或右端后一位如果是0将不显示。 0表示数字，左端第一位或右端最后一位如果是0将保留。
	 * %表示百分号
	 * @param parNum 被格式化数字
	 * @param parFormat 格式化样式
	 * @return 返回格式化后的字符串
	 */
	public static String formatBFB(double parNum, String parFormat) {
		if (parFormat == null || parFormat.equals("")) {
			return null;
		}
		String endString = null;
		DecimalFormat df = null;
		try {
			df = (DecimalFormat) NumberFormat.getPercentInstance();
			df.applyPattern(parFormat);
			endString = df.format(parNum);
		} catch (Exception ex) {

			ex.printStackTrace();
		}
		return endString;
	}

	/**
	 * 检索double数组中的最大值
	 * @param parArray 被检索的数组
	 */
	public static double findMax(double[] parArray) {
		return NumberUtils.max(parArray);
	}

	/**
	 * 检索double数组中的最小值
	 * @param parArray 被检索的数组
	 */
	public static double findMix(double[] parArray) {
		return NumberUtils.min(parArray);
	}

	/**
	 * 将Double数组转换为double数组
	 * @param array 将要转换的对象数组
	 */
	public static double[] toObject(Double[] array) {
		return ArrayUtils.toPrimitive(array);
	}

	/**
	 * 取一个数的相反数
	 * @param parStr
	 * @return
	 */
	public static double tonudouble(String parStr) {
		double mid = 0;
		if (parStr != null && parStr.equals("") == false) {
			double x = Double.parseDouble(parStr);
			if (x >= 0) {
				String xx = "-" + String.valueOf(x);
				mid = Double.parseDouble(xx);
			} else {
				mid = Math.abs(x);
			}
		}
		return mid;
	}
}
